package eval;

import network.Device;
import network.Network;
import network.Port;
import networkLoader.FBNetwork;
import org.jgrapht.Graph;
import org.jgrapht.Graphs;
import org.jgrapht.graph.DefaultEdge;
import org.jgrapht.graph.SimpleGraph;
import org.jgrapht.traverse.BreadthFirstIterator;

import java.util.*;

public class Distribution {
    static Map<String, Integer> nameToTime = new HashMap<>();
    static Graph<String, DefaultEdge> graph;
    static List<Integer> damppings = new ArrayList<>(Arrays.asList(0, 2, 4, 8, 16, 32, 60));
    static List<Integer> retransmit = new ArrayList<>();
    public static void main(String[] args) {
        for (int i = 0; i < 30; i++) {
            retransmit.add(i);
        }
        Network network = FBNetwork.getNetwork();
        for (Device device : network.getAllDevices()) {
            nameToTime.put(device.getName(), Integer.MAX_VALUE);
        }
        graph = networkToGraph(network);
        BreadthFirstIterator<String, DefaultEdge> it = new BreadthFirstIterator<>(graph, "rsw-0-0");
        while (it.hasNext()) {
            getTime(it.next());
        }
        for (Map.Entry<String, Integer> entry : nameToTime.entrySet()) {
            nameToTime.put(entry.getKey(), entry.getValue() + getRandom(damppings).get());
        }
        nameToTime.values().forEach(System.out::println);
    }

    private static void getTime(String current) {
        if (current.equals("rsw-0-0")) {
            nameToTime.put(current, 0);
        } else {
            int time = Graphs.neighborSetOf(graph, current).stream().map(s -> nameToTime.get(s)).min(Integer::compareTo).get();
            time += getRandom(retransmit).get();
//            if (Math.random() < 0.1) {
//                time += 60;
//            } else {
//                time += 1;
//            }
            nameToTime.put(current, time);
        }
    }

    public static <E> Optional<E> getRandom (Collection<E> e) {

        return e.stream()
                .skip((int) (e.size() * Math.random()))
                .findFirst();
    }

    public static Graph<String, DefaultEdge> networkToGraph(Network network) {
        Graph<String, DefaultEdge> graph = new SimpleGraph<>(DefaultEdge.class);
        for (Device device : network.getAllDevices()) {
            graph.addVertex(device.getName());
        }
        for (Device device : network.getAllDevices()) {
            for (Port port : device.getPorts()) {
                if (port.getPeerDevice() == null) {
                    continue;
                }
                graph.addEdge(device.getName(), port.getPeerDevice().getName());
            }
        }
        return graph;
    }
}
